#include "misc/string_ext.hpp"

#include <algorithm>

bool
starts_with(const std::string &str, const std::string &prefix) {
    return str.size() >= prefix.size() && std::equal(str.cbegin(), str.cbegin() + prefix.size(), prefix.cbegin());
}

bool
ends_with(const std::string &str, const std::string &suffix) {
    return str.size() >= suffix.size() && std::equal(str.cend() - suffix.size(), str.cend(), suffix.cbegin());
}

static bool
char_check_equal_ignore_case(char c1, char c2) {
    return c1 == c2 || ::toupper(c1) == ::toupper(c2);
}

bool
starts_with_ignore_case(const std::string &str, const std::string &prefix) {
    return str.size() >= prefix.size() && std::equal(str.cbegin(), str.cbegin() + prefix.size(), prefix.cbegin(), char_check_equal_ignore_case);
}

bool
ends_with_ignore_case(const std::string &str, const std::string &suffix) {
    return str.size() >= suffix.size() && std::equal(str.cend() - suffix.size(), str.cend(), suffix.cbegin(), char_check_equal_ignore_case);
}

void
lower_string(std::string &s) {
    std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}

std::string
to_lower_string(const std::string &s) {
    std::string s1(s);
    lower_string(s1);
    return std::move(s1);
}

int
compare_string(const std::string &a, const std::string &b) {
    return std::lexicographical_compare(
        std::begin(a), std::end(a),
        std::begin(b), std::end(b)
    );
}

static bool
char_compare_ignore_case(char c1, char c2) {
    return ::toupper(c1) < ::toupper(c2);
}

int
compare_string_ignore_case(const std::string &a, const std::string &b) {
    return std::lexicographical_compare(
        std::begin(a), std::end(a),
        std::begin(b), std::end(b),
        char_compare_ignore_case
    );
}
